package com.kexun.db;

import com.kexun.annotation.Column;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DBUtils {
    private static Connection conn = null;
    private static PreparedStatement ps = null;
    private static ResultSet rs = null;
    private static String classname = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://127.0.0.1:3306/mvc?useUnicode=true&&characterEncoding=UTF-8";
    private static String username = "root";
    private static String password = "root";

    // 获取连接
    private static void getCon() {
        try {
            Class.forName(classname);
            conn = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            throw new RuntimeException("数据库连接失败");
        }
    }
    // 关闭连接

    public static void close() {
        try {
            if (rs != null) {
                rs.close();
            }
            if (ps != null) {
                ps.close();
            }
            if (conn != null) {
                conn.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("数据库连接关闭失败");
        }

    }

    public static <T> List<T> find(String sql, Class<T> cls, Object... objects) {
        excute(sql, objects);
        List<T> resultSetHander = resultSetHander(rs, cls);
        close();
        return resultSetHander;
    }

    public static void excute(String sql, Object... objects) {
        getCon();
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                ps.setObject(i + 1, objects[i]);
            }
            rs = ps.executeQuery();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static <T> T findOne(String sql, Class<T> cls, Object... objects) {
        excute(sql, objects);
        List<T> ts = resultSetHander(rs, cls);
        close();
        if (ts != null && ts.size() > 0) {
            return ts.get(0);
        } else {
            return null;
        }
    }

    @SuppressWarnings("unused")
    private static <T> List<T> resultSetHander(ResultSet rs, Class<T> cls) {

        List<T> resultList = new ArrayList<T>();

        try {

            if (rs != null) {

                // 获取表结构

                ResultSetMetaData metaData = rs.getMetaData();

                // 获取cls所有的属性

                Field[] fields = cls.getDeclaredFields();

                // 如果rs存在下一条记录

                while (rs.next()) {

                    // 创建一个对象保存当前行查出来了的值

                    T bean = cls.newInstance();

                    // 遍历当前行所有的列
                    for (int i = 0; i < metaData.getColumnCount(); i++) {

                        // 得到列名

                        String columnName = metaData.getColumnName(i + 1);

                        // 得到列值

                        Object columnValue = rs.getObject(i + 1);

                        // 迭代所有cls所有属性
                        for (Field field : fields) {

                            // 因为数据库字段名和实体类名可能不一样 这里使用注解进行标记
                            // 判断是否有注解 有注解就使用注解上标注的字段名 没有注解就使用属性名
                            if (field.isAnnotationPresent(Column.class)) {

                                // 在有注解的情况下将bean属性上注解的value与数据库字段名匹配

                                Column column = field.getAnnotation(Column.class);

                                if (column.value().equalsIgnoreCase(columnName)) {

                                    // 装配到bean

                                    BeanUtils.setProperty(bean, field.getName(), columnValue);
                                    // 跳出循环

                                    break;
                                }

                            } else {
                                // 在没有注解的情况下和bean属性名和数据库字段名匹配

                                if (field.getName().equalsIgnoreCase(columnName)) {
                                    // 装配到bean
                                    BeanUtils.setProperty(bean, field.getName(), columnValue);
                                    // 跳出循环

                                    break;
                                }
                            }
                        }
                    }
                    // 将bean添加到
                    resultList.add(bean);

                }

            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return resultList;
    }

    public static boolean update(String sql, Object... objects) {
        getCon();
        int update = 0;
        try {
            ps = conn.prepareStatement(sql);
            for (int i = 0; i < objects.length; i++) {
                ps.setObject(i + 1, objects[i]);
            }
            update = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        close();
        return update > 0 ? true : false;
    }

    public static <T> boolean add(T entity) throws Exception {
        Class<?> aClass = entity.getClass();
        String TableName = aClass.getSimpleName().toLowerCase();
        Field[] declaredFields = aClass.getDeclaredFields();

        ArrayList<String> strings = new ArrayList<>();
        for (Field declaredField : declaredFields) {
            String name = declaredField.getName();
            Column annotation = declaredField.getAnnotation(Column.class);
            if (annotation != null) {
                name = annotation.value();
            }

            declaredField.setAccessible(true);
            Object resultValue = declaredField.get(entity);
            if (resultValue != null) {
                strings.add(name + "#" + resultValue);
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("INSERT INTO ");
        stringBuilder.append(TableName);
        stringBuilder.append("(");
        for (int i = 0; i < strings.size(); i++) {
            String[] split = strings.get(i).split("#");
            String s = split[0];
            stringBuilder.append("`");
            stringBuilder.append(s);
            stringBuilder.append("`");
            if (i < strings.size() - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append(") VALUES(");
        for (int i = 0; i < strings.size(); i++) {
            String[] split = strings.get(i).split("#");
            String s = split[1];
            stringBuilder.append("'");
            stringBuilder.append(s);
            stringBuilder.append("'");
            if (i < strings.size() - 1) {
                stringBuilder.append(",");
            }
        }
        stringBuilder.append(")");
        String sql = stringBuilder.toString();
        System.out.println("sql:" + sql);
        return update(sql);
    }

}
